package com.kedacom.general.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.kedacom.general.listener.ConfigMapEventListener;
import com.kedacom.general.param.RequestParam;
import com.kedacom.general.result.ResponseMessage;
import com.kedacom.general.service.TransmitService;
import com.kedacom.general.util.FileUtils;
import com.kedacom.general.util.RequestBodyUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.util.UriComponentsBuilder;
import sun.misc.BASE64Encoder;

import javax.servlet.http.HttpServletRequest;
import javax.swing.filechooser.FileSystemView;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.*;

@Slf4j
@Service
public class TransmitServiceImpl implements TransmitService {
    @Autowired
    private RestTemplate restTemplate;
    @Override
    public ResponseMessage transmit(HttpServletRequest request) {
        // 获取请求参数体
        try {
            RequestParam requestParam = RequestBodyUtil.getRequestParam(request);
            log.info("**********************后置服务获取到的参数："+requestParam);
            JSONObject parameter = requestParam.getParam();
            RequestParam requestParam1 = parameter.toJavaObject(RequestParam.class);

            String param1Url1 = requestParam1.getUrl();
            StringBuffer transmitUrl=new StringBuffer();
            String[] split = param1Url1.split("/");
            String param1Url="";
            for (int i = 2; i < split.length; i++) {
                param1Url=param1Url+"/"+split[i];
            }

            MapPropertySource previousmap = ConfigMapEventListener.CONFIG_PREVIOUSMAP;
            log.info("************统一配置信息previousmap"+ JSON.toJSONString(previousmap));
            Map<String, Object> source = previousmap.getSource();
            if (! CollectionUtils.isEmpty(source)){
                for (Map.Entry<String, Object> stringStringEntry : source.entrySet()) {
                    if (stringStringEntry.getKey().startsWith("transmit")){
                        int index = stringStringEntry.getKey().indexOf(".");
                        String substring = stringStringEntry.getKey().substring(index + 1);
                        if (StringUtils.equals(split[2],substring)){
                            log.info("************统一配置信息匹配到key值"+ stringStringEntry.getKey());
                            transmitUrl.append(stringStringEntry.getValue().toString());
                            break;
                        }
                    }
                }
            }
            if (StringUtils.isBlank(transmitUrl)){
                log.error("**********************没有匹配对应的后端服务地址，默认给https://kstp-yth.devdolphin.com");
                transmitUrl.append("https://kstp-yth.devdolphin.com");
            }
            String url = transmitUrl+param1Url;
            HttpHeaders headers = new HttpHeaders();
            if (!CollectionUtils.isEmpty(requestParam1.getHeaderMap())){
                for (String s : requestParam1.getHeaderMap().keySet()) {
                    headers.add(s,requestParam1.getHeaderMap().get(s));
                }
            }
            Map<String, Object> params = JSONObject.parseObject(requestParam1.getParam().toJSONString(), new TypeReference<Map<String, Object>>(){});
            List<Map<String, Object>> params1 = JSONObject.parseObject(requestParam1.getParam1().toJSONString(), new TypeReference<List<Map<String, Object>>>(){});

            try {
                ResponseMessage httpPostResult = new ResponseMessage();
                HttpEntity<Map<String, Object>> entity = new HttpEntity<>(params, headers);
                if (StringUtils.equals("GET",requestParam1.getMethod())){
                    UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
                    for (Map.Entry<String, Object> e : params.entrySet()) {
                        builder.queryParam(e.getKey(), e.getValue());
                    }
                    // 在此处拼接真实请求地址  "?pageNo=1&pageSize=999
                    String realUrl = builder.build().toString();
                    HttpEntity<JSONObject> httpEntity = new HttpEntity<>(null, headers);
                    log.info("**********************GET请求转发应用服务端路径"+realUrl+",参数："+httpEntity.toString());
                    if (realUrl.contains("login_page/queryPic") || realUrl.contains("download")){
                        ResponseEntity<byte[]> exchange = restTemplate.exchange(realUrl, HttpMethod.GET, httpEntity, byte[].class);

                        BASE64Encoder base64Encoder = new BASE64Encoder();
                        String encode = base64Encoder.encode(exchange.getBody());
                        HashMap<String, Object> map = new HashMap<>();
                        map.put("baseCode",encode);
                        httpPostResult.setResult(map);
                    }else{
                        ResponseEntity<ResponseMessage> exchange = restTemplate.exchange(realUrl, HttpMethod.GET, httpEntity, ResponseMessage.class);
                        httpPostResult= exchange.getBody();
                    }
                }else if (StringUtils.equals("POST",requestParam1.getMethod())){
                    if (headers.containsKey("Content-Type") && headers.get("Content-Type").get(0).contains("multipart/form-data")){
                        String fileParam="file";
                        MultipartFile file = null;
                        for (Map.Entry<String, Object> e : params.entrySet()) {
                            // 目前只支持一个文件上传
                            MultipartFile multipartFile = FileUtils.base64ToMultipartFile(e.getValue().toString());
                            if (multipartFile!=null){
                                file=multipartFile;
                                fileParam=e.getKey();
                            }
                        }
                        if (file!=null){
                            File file1 = FileUtils.multipartFileToFile(file);
                            FileSystemResource resource = new FileSystemResource(file1);
                            MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
                            param.add(fileParam, resource);
                            log.info("**********************POST请求文件上传转发应用服务端路径"+url+",参数："+param.toString());
                            httpPostResult = restTemplate.postForObject(url, param, ResponseMessage.class);
                            // 表示该文件不是文件夹
                            if (file1.isFile()) {
                                file1.delete();
                            }
                        }else{
                            log.info("**********************POST请求转发应用服务端路径"+url+",参数："+entity.toString());
                            httpPostResult = restTemplate.postForObject(url, entity, ResponseMessage.class);
                        }
                    }else{
                        if (headers.containsKey("Content-Type") && headers.get("Content-Type").get(0).contains("application/x-www-form-urlencoded")){
                            //参数
                            MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap();
                            for (String s : params.keySet()) {
                                paramMap.put(s, Collections.singletonList(params.get(s)));
                            }
                            //封装请求头
                            RequestEntity requestEntity = RequestEntity
                                    .post(new URI("")) // 可以不填
                                    .contentType(MediaType.APPLICATION_FORM_URLENCODED) // 参数传输类型 url编码格式 application/x-www-form-urlencoded
                                    .accept(MediaType.ALL).acceptCharset(StandardCharsets.UTF_8)
                                    .body(paramMap);
                            //基于注解映射对应实体
                            httpPostResult = restTemplate.postForEntity(url, requestEntity, ResponseMessage.class).getBody();
                        }else{
                            if (!CollectionUtils.isEmpty(params1)){
                                HttpEntity<List<Map<String, Object>>> entity1 = new HttpEntity<>(params1, headers);
                                log.info("**********************POST请求转发RAW数组类型参数应用服务端路径"+url+",参数："+entity1.toString());
                                httpPostResult = restTemplate.postForObject(url, entity1, ResponseMessage.class);
                            }else{
                                log.info("**********************POST请求转发应用服务端路径"+url+",参数："+entity.toString());
                                httpPostResult = restTemplate.postForObject(url, entity, ResponseMessage.class);
                            }
                        }

                    }
                }else if (StringUtils.equals("PUT",requestParam1.getMethod())){
                    log.info("**********************PUT请求转发应用服务端路径"+url+",参数："+entity.toString());
                    httpPostResult = restTemplate.exchange(url, HttpMethod.PUT, entity, ResponseMessage.class).getBody();
                }
                return httpPostResult;
            } catch (Exception e) {
                log.error("*********************************系统异常"+e.toString());
                return new ResponseMessage("系统异常",null,500,"-1");
            }
        } catch (IOException e) {
            log.error("*********************************系统异常"+e.toString());
            return new ResponseMessage("系统异常",null,500,"-1");
        }
    }

    /**
     * 将Byte数组转换成文件
     * @param bytes    byte数组
    //* @param filePath 文件路径  如 D://test/ 最后“/”结尾
     */
    public static void fileToBytes(byte[] bytes) {
        //文件名
        String name = FileSystemView.getFileSystemView().getHomeDirectory() + "\\" + DateUtil.format(new Date(), DatePattern.PURE_TIME_PATTERN) + ".xls";

        BufferedOutputStream bos = null;
        FileOutputStream fos = null;
        File file = null;
        try {

            file = new File(name);
            if (!file.getParentFile().exists()) {
                //文件夹不存在 生成
                file.getParentFile().mkdirs();
            }
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            bos.write(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
